package com.fh.shop.api.member.biz;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fh.shop.api.common.ResponseEnum;
import com.fh.shop.api.common.ServerResponse;
import com.fh.shop.api.common.SystemConst;
import com.fh.shop.api.member.mapper.IMemberMapper;
import com.fh.shop.api.member.param.EditPasswordParam;
import com.fh.shop.api.member.param.LoginParam;
import com.fh.shop.api.member.param.MemberParam;
import com.fh.shop.api.member.po.Member;
import com.fh.shop.api.member.vo.MemberVo;
import com.fh.shop.api.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Base64;
import java.util.UUID;

@Service("memberService")
@Transactional(rollbackFor = Exception.class)
public class IMemberServiceImpl implements IMemberService {

    @Autowired
    private IMemberMapper memberMapper;
    @Autowired
    private MailUtil mailUtil;
    @Value("${mail.active.member.title}")
    private String mailTitle;

    @Override
    public ServerResponse reg(MemberParam memberParam) {
        String confirmPassword = memberParam.getConfirmPassword();
        String smsCode = memberParam.getSmsCode();
        String mail = memberParam.getMail();
        String memberName = memberParam.getMemberName();
        String nickName = memberParam.getNickName();
        String password = memberParam.getPassword();
        String phone = memberParam.getPhone();
        // 验证非空
        if (StringUtils.isEmpty(confirmPassword) || StringUtils.isEmpty(smsCode)
                || StringUtils.isEmpty(mail) || StringUtils.isEmpty(memberName)
                || StringUtils.isEmpty(nickName) || StringUtils.isEmpty(password)
                || StringUtils.isEmpty(phone)) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_IS_NULL);
        }
        // 手机号的正则验证
        if (!ValidateUtil.isPhone(phone)) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_PHONE_IS_ERROR);
        }
        // 邮箱的正则验证
        if (!ValidateUtil.isMail(mail)) {
            return ServerResponse.error(ResponseEnum.MAIL_IS_ERROR);
        }
        // 密码是否一致
        if (!password.equals(confirmPassword)) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_PASSWORD_MISMATCH);
        }
        // 验证短信验证码是否正确
        String code = RedisUtil.get(KeyUtil.buildSMSPhoneKey(phone));
        if (!smsCode.equals(code)) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_SMS_CODE_IS_ERROR);
        }
        // 验证会员名的唯一性
        QueryWrapper<Member> memberNameQueryWrapper = new QueryWrapper<>();
        memberNameQueryWrapper.eq("membername", memberName);
        Member member = memberMapper.selectOne(memberNameQueryWrapper);
        if (member != null) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_NAME_IS_EXIST);
        }
        // 验证手机号的唯一性
        QueryWrapper<Member> memberPhoneQueryWrapper = new QueryWrapper<>();
        memberPhoneQueryWrapper.eq("phone", phone);
        Member member1 = memberMapper.selectOne(memberPhoneQueryWrapper);
        if (member1 != null) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_PHONE_IS_EXIST);
        }
        // 验证邮箱的唯一性
        QueryWrapper<Member> memberMailQueryWrapper = new QueryWrapper<>();
        memberMailQueryWrapper.eq("mail", mail);
        Member member2 = memberMapper.selectOne(memberMailQueryWrapper);
        if (member2 != null) {
            return ServerResponse.error(ResponseEnum.MEMBER_REG_MAIL_IS_EXIST);
        }
        // 插入会员信息
        // 子类自动转换为父类
        memberMapper.insert(memberParam);
        // 给会员发邮件 [接口安全的问题]【jwt解决的是 登录后能访问的 接口安全的问题】
        // 公开的接口【不登录就能访问的接口】:一部分确实就是让所有人都能访问操作的；但有一部分需要做安全处理的
        // 登录后才能访问的接口:jwt
        // uuid <--> id
        String uuid = UUID.randomUUID().toString();
        Long id = memberParam.getId();
        // 因为发送邮件 要走外网，所以 如果网速慢，会导致 注册后，跳转到 成功页面，等待的时间特别长，这肯定是不合适的。
        // 但我们有不能 不发邮件 【待解决的小bug】
        mailUtil.sendMail(mail, mailTitle, "<h3>恭喜您注册成功，请<a href='http://localhost:8082/api/members/active/"+uuid+"'>激活</a>后，进行登录！！！</h3>");
        RedisUtil.setEx(KeyUtil.buildActiveKey(uuid), id+"", SystemConst.ACTIVE_UUID_EXPIRE_TIME);
        // 马上删除redis中的数据
        RedisUtil.delete(KeyUtil.buildSMSPhoneKey(phone));
        return ServerResponse.success();
    }

    @Override
    public ServerResponse login(LoginParam loginParam) {
        // 非空判断
        String memberName = loginParam.getMemberName();
        String password = loginParam.getPassword();
        if (StringUtils.isEmpty(memberName) || StringUtils.isEmpty(password)) {
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_IS_NULL);
        }
        // 会员名是否正确
        QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("memberName", memberName);
        Member member = memberMapper.selectOne(memberQueryWrapper);
        if (member == null) {
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_NAME_ERROR);
        }
        // 密码是否正确
        String dbPassword = member.getPassword();
        if (!password.equals(dbPassword)) {
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_PASSWORD_ERROR);
        }
        // 状态是否激活
        Integer status = member.getStatus();
        if (status.intValue() == SystemConst.MEMBER_STATUS_INACTIVE) {
            return ServerResponse.error(ResponseEnum.MEMBER_LOGIN_STATUS_ERROR);
        }
        // 构建会员信息
        MemberVo memberVo = new MemberVo();
        Long memberId = member.getId();
        String nickName = member.getNickName();
        memberVo.setId(memberId);
        memberVo.setNickName(nickName);
        String uuid = UUID.randomUUID().toString();
        memberVo.setUuid(uuid);
        // 将java对象转为json格式的字符串
        String memberVoJson = JSON.toJSONString(memberVo);
        String base64MemberJson = Base64.getEncoder().encodeToString(memberVoJson.getBytes());
        // 生成签名
        String sign = Md5Util.sign(memberVoJson, SystemConst.SECRET);
        String base64Sign = Base64.getEncoder().encodeToString(sign.getBytes());
        // 将会员信息和签名响应给客户端 x.y ;第三方的jwt【x.y.z】 token
        String token = base64MemberJson + "." + base64Sign;
        // 存入redis中，设置过期时间
        RedisUtil.setEx(KeyUtil.buildMemberKey(memberId), uuid, SystemConst.MEMBER_EXPIRE_TIME);
        // 响应给客户端 token
        return ServerResponse.success(token);
    }

    @Override
    public ServerResponse updatePassword(EditPasswordParam passwordParam) {
        String oldPwd = passwordParam.getOldPwd();
        String newPwd = passwordParam.getNewPwd();
        String confirmPwd = passwordParam.getConfirmPwd();
        if (StringUtils.isEmpty(oldPwd) || StringUtils.isEmpty(newPwd) || StringUtils.isEmpty(confirmPwd)) {
            return ServerResponse.error(ResponseEnum.MEMBER_PWD_IS_NULL);
        }
        if (!newPwd.equals(confirmPwd)) {
            return ServerResponse.error(ResponseEnum.MEMBER_PWD_IS_MISMATCH);
        }
        // 验证旧密码是否正确
        Long memberId = passwordParam.getMemberId();
        Member dbMember = memberMapper.selectById(memberId);
        String password = dbMember.getPassword();
        if (!oldPwd.equals(password)) {
            return ServerResponse.error(ResponseEnum.MEMBER_PWD_OLD_IS_ERROR);
        }
        // 更新密码
        Member member = new Member();
        member.setId(memberId);
        member.setPassword(newPwd);
        memberMapper.updateById(member);
        // 注销
        RedisUtil.delete(KeyUtil.buildMemberKey(memberId));
        return ServerResponse.success();
    }

    @Override
    public int activeMember(String uuid) {
        String key = KeyUtil.buildActiveKey(uuid);
        String id = RedisUtil.get(key);
        if (StringUtils.isEmpty(id)) {
            return SystemConst.MEMBER_ACTIVE_ERROR;
        }
        Member member = new Member();
        member.setId(Long.parseLong(id));
        member.setStatus(SystemConst.MEMBER_STATUS_ACTIVE);
        memberMapper.updateById(member);
        //
        RedisUtil.delete(key);
        return SystemConst.MEMBER_ACTIVE_OK;
    }

    @Override
    public ServerResponse sendActiveMail(String mail) {
        // 验证邮箱格式是否合法
        if (!ValidateUtil.isMail(mail)) {
            return ServerResponse.error(ResponseEnum.MAIL_IS_ERROR);
        }
        // 验证邮箱是否存在
        QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("mail", mail);
        Member member = memberMapper.selectOne(memberQueryWrapper);
        if (member == null) {
            return ServerResponse.error(ResponseEnum.MEMBER_ACTIVE_MAIL_NOT_EXIST);
        }
        // 判断是否已经激活
        Integer status = member.getStatus();
        if (status.intValue() == SystemConst.MEMBER_STATUS_ACTIVE) {
            return ServerResponse.error(ResponseEnum.MEMBER_IS_ACTIVE);
        }
        // 发送邮件[没有激活]
        // uuid <--> id/phone/mail
        String uuid = UUID.randomUUID().toString();
        mailUtil.sendMail(mail, mailTitle, "<h3>恭喜您注册成功，请<a href='http://localhost:8082/api/members/mail/active/"+uuid+"'>激活</a>后，进行登录！！！</h3>");
        RedisUtil.setEx(KeyUtil.buildActiveKey(uuid), mail, SystemConst.ACTIVE_UUID_EXPIRE_TIME);
        return ServerResponse.success();
    }

    @Override
    public boolean activeMailMember(String uuid) {
        String key = KeyUtil.buildActiveKey(uuid);
        String mail = RedisUtil.get(key);
        if (StringUtils.isEmpty(mail)) {
            return false;
        }
        Member member = new Member();
        member.setStatus(SystemConst.MEMBER_STATUS_ACTIVE);
        QueryWrapper<Member> memberQueryWrapper = new QueryWrapper<>();
        memberQueryWrapper.eq("mail", mail);
        memberMapper.update(member, memberQueryWrapper);
        //
        RedisUtil.delete(key);
        return true;
    }
}
